﻿package rosa.services 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	
	import rosa.events.EventHandlerFactory;
	import rosa.events.IEventHandler;
	import rosa.events.RosaEvent;		

	/**
	 * @author ddt
	 */
	dynamic public class ServiceProxy extends Proxy implements IEventDispatcher
	{
		private var service:AbsRosaService;
		
		/** Contructs a new AbsRosaService instance
		 * 
		 * @param serviceName Name of the remote object to invoke
		 * @param eventHandling EventHandlingFeature enum. Describes how the class dispatches the events in the invokation lifetime
		 * @param callingStrategy CallingStrategyFeature enum. Describes how the multiple calls on the same object are handled
		 * @param view When using the automatic view event wiring feature this parameter targets to the object (the view) in where the event handlers are located
		 * 
		 */
		private var __eventHandling:String;		private var eventHandler:IEventHandler;
		private var eventDispatcher:EventDispatcher;

		/**
		 * IEventHandler implementation
		 * @see rosa.events.IEventHandler
		 */
		public function get eventHandling():String
		{
			return __eventHandling;
		}
		public function ServiceProxy(
										serviceName:String = "",
										eventHandling:String = "dispatchSubscriber",
										callingStrategy:String = "parallelCalls",
										view:Object = null
										)
		{
			__eventHandling = eventHandling;
			eventHandler = EventHandlerFactory.create(eventHandling, this,view);
			eventDispatcher = new EventDispatcher(this);
			service = new AbsRosaService(serviceName,eventHandling,callingStrategy,view);
			service.addEventListener(RosaEvent.RESULT, redirectEvent);
			service.addEventListener(RosaEvent.CALL, redirectEvent);
			service.addEventListener(RosaEvent.FAULT, redirectEvent);
			service.addEventListener(RosaEvent.RESPONSE, redirectEvent);
		}

		override flash_proxy function callProperty(methodName:*, ... args):*
		{
			trace("callProperty: "+methodName,args);
			service.addEventListener(methodName+"Result", redirectEvent);
			service.addEventListener(methodName+"Fault", redirectEvent);
			service.addEventListener(methodName+"Response", redirectEvent);
			service.addEventListener(methodName+"Call", redirectEvent);
			var realArgs:Array = new Array().concat(args);
			realArgs.unshift(methodName);
			service.callExternal.apply(service,realArgs);
			return null;
		}
		override flash_proxy function getProperty(name:*):* {
			trace("getProperty");
			return 	function(...args):void
					{
						trace("llamada:",name,args,"service: "+service);
						service.callExternal.apply(service,args);
					};
		}
		
		private function redirectEvent(event:RosaEvent):void
		{
			// FIXME Prueba a traves del service.eventHandler
			eventHandler.handleEvent(event);
		}
		
		// Implementation for IEventDispatcher
		
		public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, weakRef:Boolean = false):void {
			eventDispatcher.addEventListener(type, listener, useCapture, priority, weakRef);
		}
		   
		public function dispatchEvent(event:Event):Boolean {
			return eventDispatcher.dispatchEvent(event);
		}
		   
		public function hasEventListener(type:String):Boolean {
			return eventDispatcher.hasEventListener(type);
		}
		   
		public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
			eventDispatcher.removeEventListener(type, listener, useCapture);
		}
		   
		public function willTrigger(type:String):Boolean {
			return eventDispatcher.willTrigger(type);
		}
	}
}